{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "d8fdb577",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import math\n",
    "from tqdm import tqdm\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "format_data = {\n",
    "        \"device_id\":[],\n",
    "        \"cpu_id\":[],\n",
    "        \"record_id\":[],\n",
    "        \"timestamp\":[],\n",
    "        \"process_id\":[],\n",
    "        \"trace_action\":[],\n",
    "        \"operation_type\":[], #N操作的时候，没有扇区num，没有IOsize，只有进程name\n",
    "        \"sector_num\":[],\n",
    "        \"IO_size\":[],\n",
    "        \"process_name\":[]\n",
    "    }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "761f0925",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(19335542, 1)\n",
      "                                                   0\n",
      "0  259,2   26  1347286   686.462212380  4021  U  ...\n",
      "1  259,2   26  1347287   686.462212614  4021  I  ...\n",
      "2  259,2   26  1347288   686.462213510  4021  D  ...\n",
      "3  259,2   25  1256089   686.462216964  4025  Q  ...\n",
      "4  259,2   25  1256090   686.462217682  4025  G  ...\n"
     ]
    }
   ],
   "source": [
    "def get_data():\n",
    "    data = pd.read_csv('../data_set/map-3.csv',delimiter ='\\t',header=None)\n",
    "    #data = pd.read_csv('../data_set/ssdtrace-sample',delimiter ='\\t',header=None)\n",
    "    return data   \n",
    "data = get_data()\n",
    "print(data.shape)\n",
    "print(data.head())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "6e97156b",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████████████████████████████████████████████████████████████| 19335542/19335542 [01:52<00:00, 171507.52it/s]\n"
     ]
    }
   ],
   "source": [
    "def get_format_data(data):\n",
    "    global error_data\n",
    "    all_data = []\n",
    "    error_data = []\n",
    "    for line in tqdm(data[0]):\n",
    "        lst = line.split(' ')\n",
    "        true_data = []\n",
    "        for i in lst:\n",
    "            if len(i)>0 :\n",
    "                #print(i)\n",
    "                true_data.append(i)\n",
    "        if len(true_data)>6:\n",
    "            all_data.append(true_data)\n",
    "        else:\n",
    "            error_data.append(true_data)\n",
    "    return all_data\n",
    "lst_data = get_format_data(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "f7d3a389",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[['259,2', '26', '1347286', '686.462212380', '4021', 'U', 'N', '[java]', '1'], ['259,2', '26', '1347287', '686.462212614', '4021', 'I', 'RS', '852110608', '+', '8', '[java]'], ['259,2', '26', '1347288', '686.462213510', '4021', 'D', 'RS', '852110608', '+', '8', '[java]'], ['259,2', '25', '1256089', '686.462216964', '4025', 'Q', 'R', '560297216', '+', '16', '[java]'], ['259,2', '25', '1256090', '686.462217682', '4025', 'G', 'R', '560297216', '+', '16', '[java]']]\n",
      "[]\n"
     ]
    }
   ],
   "source": [
    "print(lst_data[:5])\n",
    "print(error_data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "243262bd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['259,2', '4', '2099202', '907.719684880', '0', 'C', 'WS', '0', '[0]']\n",
      "['259,2', '9', '2109947', '934.962219578', '0', 'C', 'WS', '0', '[0]']\n",
      "{'N', 'WS', 'FWS', 'WFS'}\n"
     ]
    }
   ],
   "source": [
    "tp = set()\n",
    "\n",
    "for lst in lst_data:\n",
    "    if len(lst)<=9:\n",
    "        tp.add(lst[6])\n",
    "    if len(lst)<=9 and lst[6]==\"WS\": #可以看出WS类型的没有sector number  IO size为0  属于0号进程\n",
    "        print(lst)\n",
    "print(tp)  # 说明这四种情况下 没有后续的内容"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "508ce2b3",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████████████████████████████████████████████████████████████| 19335542/19335542 [01:34<00:00, 205265.21it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "19335542\n",
      "19335542\n",
      "19335542\n",
      "19335542\n",
      "19335542\n",
      "19335542\n",
      "19335542\n",
      "19335542\n",
      "19335542\n",
      "19335542\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "\n",
    "for lst in tqdm(lst_data):\n",
    "\n",
    "    if lst[6]!='N' and lst[6]!=\"FWS\" and lst[6]!=\"WFS\" and  lst[6]!=\"WS\":#不是这个分支\n",
    "        format_data[\"device_id\"].append(lst[0])\n",
    "        format_data[\"cpu_id\"].append(lst[1])\n",
    "        format_data[\"record_id\"].append(lst[2])\n",
    "        format_data[\"timestamp\"].append(lst[3])\n",
    "        format_data[\"process_id\"].append(lst[4])\n",
    "        format_data[\"trace_action\"].append(lst[5])\n",
    "        format_data[\"operation_type\"].append(lst[6])\n",
    "        format_data[\"sector_num\"].append(lst[7])\n",
    "        format_data[\"IO_size\"].append(lst[9])\n",
    "        format_data[\"process_name\"].append(lst[-1])\n",
    "\n",
    "    else:\n",
    "        if lst[6]=='N':#不是这个分支\n",
    "            format_data[\"device_id\"].append(lst[0])\n",
    "            format_data[\"cpu_id\"].append(lst[1])\n",
    "            format_data[\"record_id\"].append(lst[2])\n",
    "            format_data[\"timestamp\"].append(lst[3])\n",
    "            format_data[\"process_id\"].append(lst[4])\n",
    "            format_data[\"trace_action\"].append(lst[5])\n",
    "            format_data[\"operation_type\"].append(lst[6]) #N\n",
    "            format_data[\"sector_num\"].append(0)\n",
    "            format_data[\"IO_size\"].append(0)\n",
    "            format_data[\"process_name\"].append(lst[-1])\n",
    "        elif lst[6]==\"WFS\": #不是这个分支\n",
    "            \n",
    "            if lst[8]!=\"+\":\n",
    "            #['259,2', '19', '3996', '7.120903570', '0', 'C', 'WFS', '499613064', '[0]']\n",
    "                format_data[\"device_id\"].append(lst[0])\n",
    "                format_data[\"cpu_id\"].append(lst[1])\n",
    "                format_data[\"record_id\"].append(lst[2])\n",
    "                format_data[\"timestamp\"].append(lst[3])\n",
    "                format_data[\"process_id\"].append(lst[4])\n",
    "                format_data[\"trace_action\"].append(lst[5])\n",
    "                format_data[\"operation_type\"].append(lst[6]) \n",
    "                format_data[\"sector_num\"].append(lst[7])\n",
    "                format_data[\"IO_size\"].append(0)\n",
    "                format_data[\"process_name\"].append(lst[-1])\n",
    "            else:\n",
    "                #['259,2', '1', '13708', '27.635742637', '1062', 'D', 'WFS', '499617592', '+', '8', '[kworker/1:1H]']\n",
    "                #['259,2', '1', '13710', '27.639087693', '4053', 'C', 'WFS', '499617592', '+', '8', '[0]']\n",
    "                format_data[\"device_id\"].append(lst[0])\n",
    "                format_data[\"cpu_id\"].append(lst[1])\n",
    "                format_data[\"record_id\"].append(lst[2])\n",
    "                format_data[\"timestamp\"].append(lst[3])\n",
    "                format_data[\"process_id\"].append(lst[4])\n",
    "                format_data[\"trace_action\"].append(lst[5])\n",
    "                format_data[\"operation_type\"].append(lst[6])\n",
    "                format_data[\"sector_num\"].append(lst[7])\n",
    "                format_data[\"IO_size\"].append(lst[9])\n",
    "                format_data[\"process_name\"].append(lst[-1])\n",
    "        elif lst[6]==\"WS\":#不是这个分支\n",
    "            if lst[-1]==\"[0]\":\n",
    "            #['259,2', '1', '64942', '132.546605808', '4086', 'C', 'WS', '0', '[0]']\n",
    "                format_data[\"device_id\"].append(lst[0])\n",
    "                format_data[\"cpu_id\"].append(lst[1])\n",
    "                format_data[\"record_id\"].append(lst[2])\n",
    "                format_data[\"timestamp\"].append(lst[3])\n",
    "                format_data[\"process_id\"].append(lst[4])\n",
    "                format_data[\"trace_action\"].append(lst[5])\n",
    "                format_data[\"operation_type\"].append(lst[6]) \n",
    "                format_data[\"sector_num\"].append(0) #用不到\n",
    "                format_data[\"IO_size\"].append(0)\n",
    "                format_data[\"process_name\"].append(lst[-1])\n",
    "            else: \n",
    "                format_data[\"device_id\"].append(lst[0])\n",
    "                format_data[\"cpu_id\"].append(lst[1])\n",
    "                format_data[\"record_id\"].append(lst[2])\n",
    "                format_data[\"timestamp\"].append(lst[3])\n",
    "                format_data[\"process_id\"].append(lst[4])\n",
    "                format_data[\"trace_action\"].append(lst[5])\n",
    "                format_data[\"operation_type\"].append(lst[6])\n",
    "                format_data[\"sector_num\"].append(lst[7])\n",
    "                format_data[\"IO_size\"].append(lst[9])\n",
    "                format_data[\"process_name\"].append(lst[-1])\n",
    "            #['259,2', '2', '2638', '1.641824430', '4020', 'Q', 'WS', '7487488', '+', '2048', '[java]']\n",
    "        elif lst[6]==\"FWS\":\n",
    "            #['259,2', '1', '64940', '132.545984928', '4092', 'Q', 'FWS', '[rocksdb:bg0]']\n",
    "            format_data[\"device_id\"].append(lst[0])\n",
    "            format_data[\"cpu_id\"].append(lst[1])\n",
    "            format_data[\"record_id\"].append(lst[2])\n",
    "            format_data[\"timestamp\"].append(lst[3])\n",
    "            format_data[\"process_id\"].append(lst[4])\n",
    "            format_data[\"trace_action\"].append(lst[5])\n",
    "            format_data[\"operation_type\"].append(lst[6]) \n",
    "            format_data[\"sector_num\"].append(0) #用不到\n",
    "            format_data[\"IO_size\"].append(0)#用不到\n",
    "            format_data[\"process_name\"].append(lst[-1])\n",
    "            \n",
    "\n",
    "\n",
    "print(len(format_data[\"device_id\"]))\n",
    "print(len(format_data[\"cpu_id\"]))\n",
    "print(len(format_data[\"record_id\"]))\n",
    "print(len(format_data[\"timestamp\"]))\n",
    "print(len(format_data[\"process_id\"]))\n",
    "print(len(format_data[\"trace_action\"]))\n",
    "print(len(format_data[\"operation_type\"]))\n",
    "print(len(format_data[\"sector_num\"]))\n",
    "print(len(format_data[\"IO_size\"]))\n",
    "print(len(format_data[\"process_name\"]))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "2accbb07",
   "metadata": {},
   "outputs": [],
   "source": [
    "                \n",
    "column_name = [ \"device_id\",\n",
    " \"cpu_id\",\n",
    " \"record_id\",\n",
    " \"timestamp\",\n",
    " \"process_id\",\n",
    " \"trace_action\",\n",
    " \"operation_type\",\n",
    " \"sector_num\",\n",
    " \"IO_size\",\n",
    " \"process_name\"]\n",
    "data = pd.DataFrame(format_data,columns=column_name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "be2cb67d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "19335542"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "load2_request_num = data.shape[0]\n",
    "load2_request_num"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4b623777",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████████████████████████████████████████████████████████████| 19335542/19335542 [01:45<00:00, 183346.61it/s]\n",
      "100%|██████████████████████████████████████████████████████████████████| 19335542/19335542 [01:43<00:00, 186245.82it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "最大时间数是: 945\n",
      "最小时间数是: 686\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\r",
      "  0%|                                                                                           | 0/26 [00:00<?, ?it/s]"
     ]
    }
   ],
   "source": [
    "\n",
    "def cnt_r_1s(beginS,deltaSecond=1):#以1s为单位  beginS 应该是float   计算[beginS,beginS+deltaSecond] 时间段内的读请求数目\n",
    "#     beginS = eval(beginS)\n",
    "    read_data = data[data[\"operation_type\"]==\"R\"]  \n",
    "    syn_read_data =  data[data[\"operation_type\"]==\"RS\"]\n",
    "    ahead_read_data  = data[data[\"operation_type\"]==\"A\"]#预读也算\n",
    "    cnt = 0\n",
    "    for occur_time in read_data[\"timestamp\"]:\n",
    "        occur_time = eval(occur_time)\n",
    "        if occur_time>=beginS and occur_time<beginS+deltaSecond:#这里是deltaSecond = 1s  是应该加1  而不是1000\n",
    "            cnt+=1\n",
    "    for occur_time in syn_read_data[\"timestamp\"]:\n",
    "        occur_time = eval(occur_time)\n",
    "        if occur_time>=beginS and occur_time<beginS+deltaSecond:#这里是1s  是应该加1  而不是1000\n",
    "            cnt+=1\n",
    "    for occur_time in ahead_read_data[\"timestamp\"]:\n",
    "        occur_time = eval(occur_time)\n",
    "        if occur_time>=beginS and occur_time<beginS+deltaSecond:#这里是1s  是应该加1  而不是1000\n",
    "            cnt+=1\n",
    "    return cnt\n",
    "                \n",
    "def cnt_w_1s(beginS,deltaSecond=1):\n",
    "#     beginS = eval(beginS) \n",
    "    write_data = data[data[\"operation_type\"]==\"W\"]  \n",
    "    cnt = 0\n",
    "    for occur_time in write_data[\"timestamp\"]:\n",
    "        occur_time = eval(occur_time)\n",
    "        if occur_time>=beginS and occur_time<beginS+deltaSecond:#这里是1s  是应该加1  而不是1000\n",
    "            cnt+=1\n",
    "    return cnt\n",
    "\n",
    "def getMaxTime(timestamp_lst):\n",
    "    #传入的是整个数据的timestamp列\n",
    "    lst = []\n",
    "    for i in tqdm(timestamp_lst):\n",
    "        lst.append(eval(i))\n",
    "    return max(lst)\n",
    "\n",
    "def getMinTime(timestamp_lst):\n",
    "    lst = []\n",
    "    for i in tqdm(timestamp_lst):\n",
    "        lst.append(eval(i))\n",
    "    return min(lst)\n",
    "\n",
    "\n",
    "#随时间的变化图  要求per second  所以是1s\n",
    "def generate_time_Xaxis(deltaSecond=1): #interval:区间的个数\n",
    "    endS = math.ceil(getMaxTime(data[\"timestamp\"])) #endSecond (已向上取整)\n",
    "    beginS = int(getMinTime(data[\"timestamp\"]))\n",
    "    print(\"最大时间数是:\",endS)\n",
    "    print(\"最小时间数是:\",beginS)\n",
    "    X_axis = [i for i in range(beginS,endS+1,deltaSecond)]\n",
    "    #print(\"X_axis\",X_axis)\n",
    "    return X_axis\n",
    "def generate_y_axis(x_axis):\n",
    "    y_axis = []\n",
    "    global read_cnt\n",
    "    global write_cnt\n",
    "    read_cnt = []  #每秒的read请求个数\n",
    "    write_cnt = [] #每秒的write请求个数\n",
    "    from tqdm import tqdm\n",
    "    for i in tqdm(range(len(x_axis))):\n",
    "        read_cnt.append(cnt_r_1s(x_axis[i]))\n",
    "        write_cnt.append(cnt_w_1s(x_axis[i]))\n",
    "\n",
    "    \n",
    "\n",
    "x_axis = generate_time_Xaxis(10) #本负载均可使用此x轴(per second)\n",
    "generate_y_axis(x_axis) #根据x对应的时间生成\n",
    "\n",
    "plt.plot(x_axis, read_cnt, marker='o', markersize=3)  # 绘制折线图，添加数据点，设置点的大小\n",
    "plt.plot(x_axis, write_cnt, marker='o', markersize=3)\n",
    "plt.legend(['read_amount', 'write_amount'])  # 设置折线名称\n",
    "plt.title(\"numbers of read and write request per second\")\n",
    "plt.xlabel(\"time_stamp\")\n",
    "plt.ylabel(\"request_amount\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d9e9dda7",
   "metadata": {},
   "outputs": [],
   "source": [
    "r = sum(read_cnt)\n",
    "w = sum(write_cnt)\n",
    "print(\"读请求数:\",r)\n",
    "print(\"写请求数:\",w)\n",
    "if sum(write_cnt)!=0:\n",
    "    read_write_ratio = r/w\n",
    "else:\n",
    "    read_write_ratio = \"no write request\"\n",
    "print(\"读写请求比例为:\",read_write_ratio)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "4e17e63b",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████████████████████████████████████████████████████████████| 19335542/19335542 [02:49<00:00, 113889.80it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "平均IOPS： 20474.298654254544\n"
     ]
    }
   ],
   "source": [
    "# 任务 3 ：计算平均IOPS\n",
    "AVG_IOPS = load2_request_num / getMaxTime(data[\"timestamp\"]) \n",
    "print(\"平均IOPS：\",AVG_IOPS)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "a61c830a",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|███████████████████████████████████████████████████████████████████████████████| 26/26 [1:10:33<00:00, 162.84s/it]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "y轴请求数目数组: [3429, 70710, 65513, 70989, 179557, 247679, 37213, 128836, 56069, 10355, 80263, 37966, 21702, 10393, 55339, 107281, 192261, 34029, 22478, 18744, 19425, 35598, 65102, 9687, 89530, 5375]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'request_amount')"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 任务4：负载的IOPS随时间变化示意图？（画图显示结果，参考示列3）？\n",
    "\n",
    "# per second \n",
    "def cnt_request_per_delta(beginS,deltaSecond=1): \n",
    "    cnt = 0\n",
    "    for occur_time in data[\"timestamp\"]:\n",
    "        occur_time = eval(occur_time)\n",
    "        if occur_time>=beginS and occur_time<beginS+deltaSecond:#这里是1s  是应该加1  而不是1000\n",
    "            cnt+=1\n",
    "    return cnt\n",
    "\n",
    "y_axis_request_cnt = []\n",
    "for i in tqdm(range(len(x_axis))): \n",
    "    y_axis_request_cnt.append(cnt_request_per_delta(x_axis[i]))\n",
    "print(\"y轴请求数目数组:\",y_axis_request_cnt)\n",
    "\n",
    "plt.plot(x_axis, y_axis_request_cnt, marker='o', markersize=3)  # 绘制折线图，添加数据点，设置点的大小\n",
    "plt.title(\"numbers of I/O request per second\")\n",
    "plt.xlabel(\"time_stamp\")\n",
    "plt.ylabel(\"request_amount\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "878667d0",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████████████████████████████████████████████████████████████| 19335542/19335542 [01:40<00:00, 191707.21it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x_axis_per_hour: [0, 1]\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 50%|██████████████████████████████████████████                                          | 1/2 [01:37<01:37, 97.77s/it]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "y_axis_request_cnt_per_hour: [19335542] hour: 0\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|████████████████████████████████████████████████████████████████████████████████████| 2/2 [03:09<00:00, 94.90s/it]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "y_axis_request_cnt_per_hour: [19335542, 0] hour: 1\n",
      "y轴请求数目数组: [19335542, 0]\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "# per hour\n",
    "def generate_time_Xaxis_per_hour(deltaHour=1): #interval:区间的个数\n",
    "    endS = math.ceil(getMaxTime(data[\"timestamp\"])/3600) #endSecond (已向上取整)\n",
    "    X_axis = [i for i in range(endS+1)]\n",
    "    #print(\"X_axis\",X_axis)\n",
    "    return X_axis\n",
    "x_axis_per_hour = generate_time_Xaxis_per_hour() \n",
    "print(\"x_axis_per_hour:\",x_axis_per_hour)\n",
    "\n",
    "y_axis_request_cnt_per_hour = []\n",
    "for i in tqdm(range(len(x_axis_per_hour))): \n",
    "    y_axis_request_cnt_per_hour.append(cnt_request_per_delta(x_axis_per_hour[i]*3600,3600)) #求出各个小时内请求的数量\n",
    "    print(\"y_axis_request_cnt_per_hour:\",y_axis_request_cnt_per_hour,\"hour:\",x_axis_per_hour[i])\n",
    "print(\"y轴请求数目数组:\",y_axis_request_cnt_per_hour)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "eaf67510",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|█████████████████████████████████████████████████████████████████| 19335542/19335542 [00:13<00:00, 1410297.58it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   0        8       16    2048       24      32      48  1608  880    104  \\\n",
      "0  1  3848770  9560046  222104  1743288  279467  110177   108  108  21155   \n",
      "\n",
      "   ...  1688  1488  736  1832  1352  1856  912  1256  1136  704  \n",
      "0  ...     8     4    4     4     4     4    4     8     4    4  \n",
      "\n",
      "[1 rows x 224 columns]\n",
      "平均请求大小为: 38.586617742600644\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "y_axis_IOsize_frequency = {}\n",
    "for item in tqdm(data[\"IO_size\"]):\n",
    "    if y_axis_IOsize_frequency.get(item)==None:\n",
    "        temp = {str(item):[1]} #全部转为字符串  使用list是为了便于转为datafrmae\n",
    "        y_axis_IOsize_frequency.update(temp)\n",
    "    else:\n",
    "        (y_axis_IOsize_frequency[str(item)])[0]+=1\n",
    "        \n",
    "# print(y_axis_IOsize_frequency.keys())\n",
    "\n",
    "IO_SIZE_TABLE = {\n",
    "    \"请求大小\":list(y_axis_IOsize_frequency.keys()),\n",
    "    \"出现次数\":list(y_axis_IOsize_frequency.values())\n",
    "}\n",
    "IO_SIZE_TABLE = pd.DataFrame(y_axis_IOsize_frequency)\n",
    "print(IO_SIZE_TABLE)\n",
    "\n",
    "\n",
    "#load2_request_num #总的请求数目\n",
    "IO_SIZE_SUM = 0\n",
    "for key,value in y_axis_IOsize_frequency.items():\n",
    "    IO_SIZE_SUM+=eval(key)*value[0]\n",
    "AVG_IO_SIZE = IO_SIZE_SUM / load2_request_num\n",
    "print(\"平均请求大小为:\",AVG_IO_SIZE)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e9d237f9",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6bef0e7d",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0d64fb78",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
